from threading import Lock, Thread
from prg.common.semaphore_base import SemaphoreItem
import threading
import time


class MessageBase(Thread):
    def __init__(self, name="thread", target=None, args=()):
        self.item_name = None
        self.group_name = None
        self.parent_item = None
        self.daemon_val = False
        self.semaphore_item = None
        current = threading.current_thread()
        name += str((int(round(time.time() * 1000))))
        if current.name is not None:
            name = "%s.%s" % (current.name, name)
        super().__init__(name=name, target=target, args=args)
        self.setDaemon(self.daemon_val)
        if hasattr(current, "group_name"):
            self.set_group_name(current.group_name)
        if hasattr(current, "semaphore_item"):
            self.semaphore_item = current.semaphore_item
        ObjectMessage.instance().add(self)

    def entry(self):
        pass

    def run(self):
        try:
            if self._target:
                super().run()
            else:
                self.entry()
        except Exception as e:
            print("thread name: %s error: %s" % (self.name, e))
        finally:
            self.release()
            self.end()

    def is_run(self):
        if self.semaphore_item is None:
            return True
        return not self.semaphore_item.ready

    def release(self):
        if self.semaphore_item is not None:
            self.semaphore_item.release()

    def create_semaphore(self, value=1):
        self.semaphore_item = SemaphoreItem(value)
        self.semaphore_item.acquire()

    def acquire(self):
        if self.semaphore_item is not None:
            self.semaphore_item.acquire()

    def create(self, class_item, **arg):
        obj = class_item(arg)
        if isinstance(obj, MessageBase):
            obj.parent_item = self
            obj.set_group_name(self.group_name)
            return obj
        return None

    def set_item_name(self, name):
        self.item_name = name

    def set_group_name(self, name):
        self.group_name = name

    def message(self, msg):
        pass

    def stop(self):
        self._stop()

    def end(self):
        print("thread %s out" % self.name)


class ObjectMessage:
    _instance_lock = Lock()

    def __init__(self):
        self.object_collect = dict()
        self.object_group = dict()

    def add(self, obj):
        if not isinstance(obj, MessageBase):
            raise Exception("not support type")
        group_name = obj.item_name
        item_name = obj.group_name
        if group_name is not None:
            if group_name not in self.object_group:
                self.object_group[group_name] = []
            self.object_group[group_name].append(obj)
        if item_name is not None:
            if item_name not in self.object_group:
                self.object_collect[item_name] = []
            self.object_collect[item_name].append(obj)

    def send_message(self, name, msg):
        if name in self.object_collect:
            for item in self.object_collect[name]:
                item.message(msg)

    def send_group_message(self, group, msg):
        if group in self.object_group:
            for item in self.object_collect[group]:
                item.message(msg)

    @staticmethod
    def instance():
        if not hasattr(ObjectMessage, "_instance"):
            with ObjectMessage._instance_lock:
                if not hasattr(ObjectMessage, "_instance"):
                    ObjectMessage._instance = ObjectMessage()
        return ObjectMessage._instance
